/**
 * @ProjectName:Backend
 * @Title: JwtUtil
 * @Package com.phrp.util
 * @Description: jwt工具类
 * @author SuShuChao
 * @date 2024/4/7 13:17
 * @version V1.0
 * Copyright (c) 2024, 2034279227@qq.com All Rights Reserved.
 */
package com.phrp.util.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;


@Component
public class JwtUtil {
    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 密钥
     */
    @Value("${jwt.secret}")
    private String secret;

    /**
     * token有效期(s)
     */
    @Value("${jwt.expiration}")
    private Long expiration;

    /**
     * token保存头部(s)
     */
    @Value("${jwt.header}")
    private String header;

    /**
     * 生成jwt token
     * 用户信息仅包含了id信息
     */
    public String generateToken(String phone) {
        Date nowDate = new Date();
        //过期时间
        Date expireDate = new Date(nowDate.getTime() + expiration * 1000);

        return Jwts.builder()
                .setHeaderParam("type", "JWT")
                .setSubject(phone)          // 用户手机号---登录用户名
                .setIssuedAt(nowDate)       // 设置签发时间
                .setExpiration(expireDate)  // 过期时间
                .signWith(SignatureAlgorithm.HS512, generateKeyByDecoders())
                .compact();
    }

    /**
     * 通过token获取用户信息
     * @param token
     * @return
     */
    public Claims getClaimByToken(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            logger.debug("validate is token error ", e);
            return null;
        }
    }

    /**
     * token是否过期
     * @return true：过期
     */
    public boolean isTokenExpired(Date expiration) {
        return expiration.before(new Date());
    }

    /**
     * 密钥加密
     * @return
     */
    private SecretKey generateKeyByDecoders() {
        return Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));
    }
    public String getSecret() {
        return secret;
    }
    public void setSecret(String secret) {
        this.secret = secret;
    }
    public long getExpire() {
        return expiration;
    }
    public void setExpire(long expire) {
        this.expiration = expire;
    }
    public String getHeader() {
        return header;
    }
    public void setHeader(String header) {
        this.header = header;
    }

    /**
     * 以下是另外一种方式
     */

    //
    // /**
    //  * 生成token
    //  * <p>
    //  * 生成token。根据传入的claims信息，设置token的claims、过期时间，
    //  * 并使用SecretKey对token进行签名生成最终的token字符串。
    //  */
    // private String generateToken(Map<String, Object> claims) {
    //     return Jwts.builder()
    //             .setClaims(claims)
    //             .setExpiration(generateExpirationDate())
    //             .signWith(generateKeyByDecoders())
    //             .compact();
    // }
    //
    // /**
    //  * 根据用户信息生成token
    //  * <p>
    //  * 根据用户信息生成一个JWT token。将用户信息转换为JSON字符串，放入claims中
    //  * 然后调用generateToken(Map<String,Object> claims)方法生成token。
    //  *
    //  * @SneakyThrows 这个异常会检测方法内部出现的异常，简化异常声明或者try
    //  */
    // @SneakyThrows
    // public String generateToken(ManagerUser managerUser) {
    //     Map<String, Object> claims = new HashMap<>();
    //     claims.put(CLAIM_KEY_USERNAME, managerUser.getPhone());
    //     claims.put(CLAIM_KEY_PASSWORD, managerUser.getPassword());
    //     claims.put(CLAIM_KEY_CREATED, new Date());
    //     return generateToken(claims);
    // }
    //
    // /**
    //  * 生成自定义key
    //  * <p>
    //  * 生成自定义的SecretKey。使用Base64解码secret属性，然后通过
    //  * Keys.hmacShaKeyFor()方法生成SecretKey
    //  */
    // private SecretKey generateKeyByDecoders() {
    //     return Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));
    // }
    //
    // /**
    //  * 从token中获取信息
    //  * <p>
    //  * 从token中解析出JWT claims。
    //  * 使用给定的token，解析出其中的claims部分，需要提供相应的密钥来解析token。
    //  */
    // private Claims getClaimsFromToken(String token) {
    //     return Jwts.parserBuilder()
    //             .setSigningKey(generateKeyByDecoders())
    //             .build()
    //             .parseClaimsJws(token)
    //             .getBody();
    // }
    //
    // /**
    //  * 从token中获取用户信息
    //  * <p>
    //  * 从token中获取用户信息。解析出其中的claims部分，需要提供相应的密钥来解析token。
    //  */
    // @SneakyThrows
    // public <T> T getUserInfoFromToken(String token, Class<T> valueType) {
    //     Claims claims = getClaimsFromToken(token);
    //     return new ObjectMapper().readValue(claims.getSubject(), valueType);
    // }
    //
    // /**
    //  * 从token中获取过期时间
    //  * <p>
    //  * 解析token中的过期时间信息，并返回对应的Date对象。
    //  */
    // private Date getExpiresDateFromToken(String token) {
    //     Claims claims = getClaimsFromToken(token);
    //     return claims.getExpiration();
    // }
    //
    // /**
    //  * 判断token是否有效
    //  * <p>
    //  * 获取token的过期时间，然后与当前时间比较，判断token是否已经过期。
    //  */
    // public boolean isTokenExpired(String token) {
    //     Date expiredDate = getExpiresDateFromToken(token);
    //     return expiredDate.after(new Date());
    // }
    //
    // /**
    //  * 刷新token
    //  * <p>
    //  * 更新token中的创建时间为当期时间，然后重新生成一个新的token。
    //  */
    // public String refreshToken(String token) {
    //     Claims claims = getClaimsFromToken(token);
    //     claims.put(CLAIM_KEY_CREATED, new Date());
    //     return generateToken(claims);
    // }
    //
    // /**
    //  * 生成token过期时间
    //  * <p>
    //  * 根据expiration属性设定的秒数，计算出一个未来的过期时间。
    //  */
    // private Date generateExpirationDate() {
    //     return new Date(System.currentTimeMillis() + expiration * 1000);
    // }

}
